<template>
  <div v-if="enable" style="padding:5px">
      <el-radio-group v-model="formType" size="small" style="padding-left:20px">
        <el-radio value="1">动态表单</el-radio>
        <el-radio value="2">外置表单</el-radio>
      </el-radio-group>
     <el-divider></el-divider>
     <div v-if="formType === '1'">
      <el-row style="padding-bottom:5px">
          <el-button type="primary" size="small"  v-show="dataList.length === 0" icon="plus" @click="dialogVisible=true">添加</el-button>
          <el-button type="primary" size="small" icon="edit-filled" @click="edit()" v-show="dataList.length > 0" >修改</el-button>
          <el-button type="primary" size="small" icon="del-filled" @click="del()" v-show="dataList.length > 0 " >删除
          </el-button>
      </el-row>
      <el-table
        :data="dataList"
        border
        size = "small"
        default-expand-all
        class="design-right">
        <el-table-column  type="expand">
        <template #default="scope">
            <el-table
                border
                size="small"
                :data="scope.row.dataBindFields"
                style="width: 100%">
              <el-table-column
                type="index"
                width="50">
              </el-table-column>
              <el-table-column
                  prop="name"
                  label="字段名称">
                </el-table-column>
              <el-table-column
                  prop="id"
                  show-overflow-tooltip
                  label="字段ID">
                </el-table-column>
              <el-table-column
                  prop="readable"
                  align="center"
                   width="80"
                  label="可读">
                  <template #header>
                    <el-checkbox @change="checkReadAll" v-model="isReadableAll">可读</el-checkbox>
                  </template>
                  <template #default="scope">
                     <el-checkbox :true-value="'true'" :false-value="'false'" v-model="scope.row.readable"></el-checkbox>
                  </template>
              </el-table-column>
                <el-table-column
                prop="writable"
                align="center"
                 width="80"
                label="可写">
                <template #header>
                  <el-checkbox @change="checkWriteAll" v-model="isWriteableAll">可写</el-checkbox>
                </template>
                 <template #default="scope">
                     <el-checkbox :true-value="'true'" :false-value="'false'" v-model="scope.row.writable"></el-checkbox>
                  </template>
              </el-table-column>
              </el-table>
        </template>
        </el-table-column>
        <el-table-column
          prop="name"
          label="表单名称">
        </el-table-column>
        <el-table-column
          prop="version"
          label="版本">
        </el-table-column>
         <el-table-column
          prop="id"
          label="表单key">
        </el-table-column>
      </el-table>
     </div>
      <div v-if="formType === '2'">
        <el-form  v-if="enable" class="act-form" label-width="100px">
          <el-form-item label="表单地址">
            <el-input  placeholder="外置表单路径必须包含'/'，否则会被识别为动态表单" v-model="outFormKey"></el-input>
          </el-form-item>
          <el-form-item label="表单只读">
            <el-checkbox :disabled="isDisable" v-model="formReadOnly"></el-checkbox>     勾选执行此审批节点时表单不可以修改。
          </el-form-item>
        </el-form>
      </div>
      <el-dialog
        title="选择动态表单"
        v-model="dialogVisible"
        append-to-body
        draggable
        width="500px">
        <el-form  ref="form" :model="inputForm"  label-width="80px">
          <!-- <el-form-item label="表单类型">
            <el-select v-model="formType" placeholder="请选择" style="width:100%">
              <el-option
                v-for="item in options"
                :key="item.value"
                :label="item.label"
                :value="item.value">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item v-if="formType === '2'" label="表单地址">
                <el-input v-model="formKey"></el-input>
          </el-form-item> -->
          <el-form-item label="表单选择" prop="selectedDyFormKey" :rules="[
                    {required: true, message:'动态表单不能为空', trigger:'blur'}
                   ]">
            <el-select v-model="inputForm.selectedDyFormKey" filterable clearable placeholder="请选择" style="width:100%">
              <el-option
                v-for="item in formOptions"
                :key="item.id"
                :label="item.name + ': v'+item.version"
                :value="item.jsonId">
              </el-option>
            </el-select>
          </el-form-item>
          <!-- <el-form-item label="表单只读">
           <el-checkbox :disabled="isDisable" v-model="formReadOnly"></el-checkbox>     勾选后，执行当前任务节点时，表单不可以修改。
         </el-form-item> -->
        </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button  @click="dialogVisible = false">取 消</el-button>
          <el-button  type="primary" @click="add()">确 定</el-button>
          </span>
      </template>
      </el-dialog>
  </div>
  </template>
  <script>
  import pick from 'lodash.pick'
  import { is } from 'jeeplus-bpmn/lib/util/ModelUtil'
  import { getBusinessObject } from 'jeeplus-bpmn/lib/util/ModelUtil'
  import elementHelper from 'jp-bpmn-js-properties-panel/lib/helper/ElementHelper'
  import formDefinitionService from '@/api/flowable/formDefinitionService'
  export default {
    props: {
      element: {
        type: Object,
        default: undefined
      },
      bpmnModeler: {
        type: Object,
        default: undefined
      },
      formOptions: {
        type: Array,
        default: []
      }
    },
    data () {
      return {
        formReadOnly: false,
        dialogVisible: false,
        formKey: '',
        outFormKey: '',
        formType: '1',
        isReadableAll: false,
        isWriteableAll: false,
        inputForm: {
          selectedDyFormKey: ''
        },
        title: '',
        name: '',
        type: '',
        address: '',
        dataList: [],
        options: [{
          value: '1',
          label: '动态表单'
        }, {
          value: '2',
          label: '外置表单'
        }]
      }
    },
    computed: {
      isDisable () {
        return is(this.element, 'bpmn:StartEvent')
      },
      enable () {
        if (!this.ensureFormKeyAndDataSupported(this.element)) {
          return false
        } else {
          return true
        }
      }
    },
    methods: {
      checkWriteAll(isWriteAll) {
        // 获取所有节点的 key 值
        if(isWriteAll){
          this.dataList[0].dataBindFields.forEach(bindField => {
            bindField.writable = 'true';
          })
        }else{
          this.dataList[0].dataBindFields.forEach(bindField => {
            bindField.writable = 'false';
          })
        }
        
      },
      checkReadAll(isReadAll) {
        // 获取所有节点的 key 值
        if(isReadAll){
          this.dataList[0].dataBindFields.forEach(bindField => {
            bindField.readable = 'true';
          })
        }else{
          this.dataList[0].dataBindFields.forEach(bindField => {
            bindField.readable = 'false';
          })
        }
      },
      ensureFormKeyAndDataSupported (element) {
        return (
          is(element, 'bpmn:StartEvent') && !is(element.parent, 'bpmn:SubProcess')
        ) || is(element, 'bpmn:UserTask')
      },
      add () {
        this.$refs['form'].validate((valid) => {
          if (valid) {
            let form = this.formOptions.filter((item) => {
              return this.inputForm.selectedDyFormKey === item.jsonId
            })[0]
            if(!form){
              return
            }
            let dataBindFields = []
            this.generateModel(JSON.parse(form.json).list, dataBindFields)
            this.dataList = []
            this.formKey = form.jsonId
            //  this.formKey = newVal
            this.bpmnModeler.get('modeling').updateProperties(this.element, { 'flowable:formKey': this.formKey })
            localStorage.setItem(this.element.id + 'dyFormKey', this.formKey)
            this.dataList.push({name: form.name, version: form.version, id: this.inputForm.selectedDyFormKey, dataBindFields: dataBindFields})
            this.dialogVisible = false
          }
        })
      },
      edit () {
        this.dialogVisible = true
      },
      del () {
        this.$confirm(`确定删除动态表单吗?`, '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          this.dataList = []
          this.inputForm.selectedDyFormKey = ''
          this.formKey = ''
          this.bpmnModeler.get('modeling').updateProperties(this.element, { 'flowable:formKey': this.formKey })
          localStorage.setItem(this.element.id + 'dyFormKey', this.formKey)
        })
      },
      generateModel (genList, dataBindFields) {
        for (let i = 0; i < genList.length; i++) {
          if (genList[i].type === 'grid') {
            genList[i].columns.forEach(item => {
              this.generateModel(item.list, dataBindFields)
            })
          } else if (genList[i].type === 'tabs' || genList[i].type === 'collapse') {
            genList[i].tabs.forEach(item => {
              this.generateModel(item.list, dataBindFields)
            })
          } else if (genList[i].type === 'report') {
          genList[i].rows.forEach(row => {
            row.columns.forEach(column => {
              this.generateModel(column.list, dataBindFields)
            })
          })
        } else if (genList[i].type === 'inline' || genList[i].type === 'card' || genList[i].type === 'dialog') {
          this.generateModel(genList[i].list, dataBindFields)
        } else {
              // 处理老版本没有dataBind值的情况，默认绑定数据
            if (genList[i].options.dataBind) {
              dataBindFields.push({'id': genList[i].model, 'name': genList[i].name, readable: 'true', writable: 'true'})
            }
          }
        }
        return dataBindFields
      },
      getExtensionElements (element) {
        let bo = getBusinessObject(element)
        return bo.extensionElements
      },
      createExtensionElements: function (element, bo) {
        var extensionElements = elementHelper.createElement('bpmn:ExtensionElements', { values: [] }, bo, this.bpmnModeler.get('bpmnFactory'))
        bo.extensionElements = extensionElements
        return extensionElements
      },
      isExtensionElements (element) {
        return is(element, 'bpmn:ExtensionElements')
      },
      getButtonsElement (element) {
        if (!this.isExtensionElements(element)) {
          return element.buttons
        } else {
          return this.getButtonsElementInsideExtensionElements(element)
        }
      },
      getButtonsElementInsideExtensionElements (extensionElements) {
        return find(extensionElements.values, function (elem) {
          return is(elem, 'flowable:Button')
        })
      },
      updateElements (tableDatas) {
        let dataBindFields = []
        if (tableDatas.length === 1 && tableDatas[0].dataBindFields) {
          dataBindFields = tableDatas[0].dataBindFields
        }
        let element = this.element
        let bo = getBusinessObject(element)
        let parent = this.getExtensionElements(element)
  
        if (!parent && typeof this.createExtensionElements === 'function') {
          parent = this.createExtensionElements(element, bo)
        }
        let objList = []
        dataBindFields.forEach((row) => {
          var formProperty = elementHelper.createElement('flowable:FormProperty', row, parent, this.bpmnModeler.get('bpmnFactory'))
          objList.push(formProperty)
        })
  
        let old = []
        if (this.element.businessObject.extensionElements) {
          this.element.businessObject.extensionElements.values.forEach((value) => {
            if (is(value, 'flowable:FormProperty')) {
              old.push(value)
            }
          })
        }
        this.bpmnModeler.get('commandStack').execute('properties-panel.update-businessobject-list', {
          element: element,
          currentObject: parent,
          propertyName: 'values',
          objectsToRemove: old
        })
  
        this.bpmnModeler.get('commandStack').execute('properties-panel.update-businessobject-list', {
          element: element,
          currentObject: parent,
          propertyName: 'values',
          objectsToAdd: objList
        })
      }
    },
    watch: {
      formReadOnly: {
        handler (newVal, oldVal) {
          if (this.element) {
            this.bpmnModeler.get('modeling').updateProperties(this.element, { 'flowable:formReadOnly': newVal })
          }
        },
        deep: true
  
      },
      formKey: {
        handler (newVal, oldVal) {
          if (this.element) {
            this.bpmnModeler.get('modeling').updateProperties(this.element, { 'flowable:formKey': newVal })
          }
        },
        deep: true
      },
      outFormKey: {
        handler (newVal, oldVal) {
          if (this.element) {
            this.formKey = newVal
            localStorage.setItem(this.element.id + 'outFormKey', newVal)
            this.bpmnModeler.get('modeling').updateProperties(this.element, { 'flowable:outFormKey': newVal })
          }
        },
        deep: true
      },
      // 'inputForm.selectedDyFormKey': {
      //   handler (newVal, oldVal) {
      //     if (this.element) {
      //       this.formKey = newVal
      //       localStorage.setItem(this.element.id + 'dyFormKey', newVal)
      //       // this.bpmnModeler.get('modeling').updateProperties(this.element, { 'flowable:dyFormKey': newVal })
      //     }
      //   },
      //   deep: false
      // },
      formType: {
        handler (newVal, oldVal) {
          if (this.element) {
            this.bpmnModeler.get('modeling').updateProperties(this.element, { 'flowable:formType': newVal })
            if (this.formType === '1') {
              this.inputForm.selectedDyFormKey = localStorage.getItem(this.element.id + 'dyFormKey') ? localStorage.getItem(this.element.id + 'dyFormKey') : ''
              this.formKey = this.inputForm.selectedDyFormKey
              let dataBindFields = []
              if (this.element.businessObject.extensionElements) {
                this.element.businessObject.extensionElements.values.forEach((value) => {
                  if (is(value, 'flowable:FormProperty')) {
                    value = pick(value, 'id', 'name', 'readable', 'writable', 'required')
                    value.readable = (value.readable === undefined ? 'true' : value.readable)
                    value.writable = (value.writable === undefined ? 'true' : value.writable)
                    dataBindFields.push(JSON.parse(JSON.stringify(value)))
                  }
                })
              }
              this.dataList = []
              if (this.formKey) {
                let node = this.formOptions.filter((item) => {
                  return item.jsonId === this.formKey
                })
                let formName = ''
                let version = ''
                if (node.length > 0) {
                  formName = node[0].name
                  version = node[0].version
                }
                this.dataList.push({id: this.formKey, version: version, name: formName, dataBindFields: dataBindFields})
              }
            } else {
              this.outFormKey = localStorage.getItem(this.element.id + 'outFormKey') ? localStorage.getItem(this.element.id + 'outFormKey') : ''
              this.formKey = this.outFormKey
            }
          }
        },
        deep: false
      },
      'element': {
        handler (newVal) {
          var bo = getBusinessObject(this.element)
          let formKey = bo.get('flowable:formKey') ? bo.get('flowable:formKey') : ''
          this.formReadOnly = bo.get('flowable:formReadOnly')
          if (bo.get('flowable:formType')) {
            this.formType = bo.get('flowable:formType')
          } else if ((formKey && formKey.indexOf('/') >= 0)) {
            this.formType = '2'
            this.bpmnModeler.get('modeling').updateProperties(this.element, { 'flowable:formType': '2' })
          } else {
            this.formType = '1'
            this.bpmnModeler.get('modeling').updateProperties(this.element, { 'flowable:formType': '1' })
          }
  
          if (this.formType === '1') {
            let dataBindFields = []
            if (this.element.businessObject.extensionElements) {
              this.element.businessObject.extensionElements.values.forEach((value) => {
                if (is(value, 'flowable:FormProperty')) {
                  value = pick(value, 'id', 'name', 'readable', 'writable', 'required')
                  value.readable = (value.readable === undefined ? true : value.readable)
                  value.writable = (value.writable === undefined ? true : value.writable)
                  dataBindFields.push(JSON.parse(JSON.stringify(value)))
                }
              })
            }
            this.dataList = []
            if (formKey) {
              let node = this.formOptions.filter((item) => {
                return item.jsonId === formKey
              })
              if (node.length === 0) {
                formDefinitionService.queryByJsonId(formKey).then((data) => {
                    let formDefinition = data
                    // this.inputForm.selectedDyFormKey = formKey
                    this.inputForm.selectedDyFormKey = ''
                    this.dataList.push({id: formKey, name: formDefinition.name, version: formDefinition.formDefinitionJson.version, dataBindFields: dataBindFields})
                }).catch(()=>{
                    this.inputForm.selectedDyFormKey = ''
                    this.dataList = []
                })
              } else {
                this.inputForm.selectedDyFormKey = formKey
                this.dataList.push({id: formKey, name: node[0].name, version: node[0].version, dataBindFields: dataBindFields})
              }
            } else {
              this.inputForm.selectedDyFormKey = ''
              this.dataList = []
            }
          } else {
            this.outFormKey = formKey
          }
        },
        immediate: true,
        deep: false
      },
      dataList: {
        handler (newVal) {
          if(this.dataList[0] && this.dataList[0].dataBindFields){
            this.isReadableAll = this.dataList[0].dataBindFields.filter( field => field.readable === 'false').length == 0;
            this.isWriteableAll = this.dataList[0].dataBindFields.filter( field => field.writable === 'false').length == 0;
          }
          if (this.element) {
            this.updateElements(newVal)
          }
        },
        immediate: true,
        deep: true
      },
    }
  }
  </script>
  <style>
    .design-right .el-table__expanded-cell[class*=cell] {
      padding: 5px 10px;
    }
  </style>
  